home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / langs / cc68x.zoo / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-04  |  12.1 KB  |  530 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <support.h>
  4. #include <unistd.h>
  5. #include "global.h"
  6. #include "patchlev.h"
  7.  
  8. #define CPP        "cpp"
  9. #define CC1        "c68"
  10. #define AS        "as68"
  11. #define LNK        "ld"
  12. #define RT_STARTUP    "%scrt0.o"
  13. #define    N_LIB_FORMS    2
  14. #define INC_ENV_VAR    "C68INC"
  15. #define LIB_ENV_VAR    "C68LIB"
  16. #define DEFAULT_INC    "c:\\c68\\include"
  17. #define DEFAULT_LIB    "c:\\c68\\lib"
  18. #define DEFAULT_EXEC    "a.out"
  19.  
  20. #define DO_PREPROCESS    0
  21. #define DO_COMPILE    1
  22. #define DO_ASSEMBLE    2
  23. #define DO_LINK        3
  24. #define UP_TO_LINK    (last_stage == DO_LINK ? DO_ASSEMBLE : last_stage)
  25.  
  26. #define LF_STARTUP    1
  27. #define LF_MATHLIB    2
  28. #define LF_STDCLIB    3
  29.  
  30. #define RM_INTERMED    1
  31. #define RM_FINAL    2
  32.  
  33. #define DEFAULT_WARN_LVL    3
  34.  
  35. #ifdef __STDC__
  36. static void usage(void);
  37. static void rename_stage(const char *);
  38. static void long_option(const char *);
  39. static char *lib_name_opts(const char *, int);
  40. static void add_lib(const char *);
  41. static void add_lib_file(int);
  42. static void add_input_file(const char *, int);
  43. static void remove_temp_files(int);
  44. static void panic_remove_temps(void);
  45. static const char *derive_dest(const char *, int);
  46. static void process_file(const char *, int);
  47. #else
  48. static void usage();
  49. static void rename_stage();
  50. static void long_option();
  51. static char *lib_name_opts();
  52. static void add_lib();
  53. static void add_lib_file();
  54. static void add_input_file();
  55. static void remove_temp_files();
  56. static void panic_remove_temps();
  57. static char *derive_dest();
  58. static void process_file();
  59. #endif
  60.  
  61. static Arguments cpp_args = {0, 0, 0},
  62.          cc1_args = {0, 0, 0},
  63.          as_args = {0, 0, 0},
  64.          lnk_args = {0, 0, 0},
  65.          c_files = {0, 0, 0},
  66.          i_files = {0, 0, 0},
  67.          s_files = {0, 0, 0},
  68.          o_files = {0, 0, 0},
  69.          new_env = {0, 0, 0},
  70.          temp_files = {0, 0, 0};
  71. static Arguments *passes[] = {&cpp_args, &cc1_args, &as_args, &lnk_args};
  72. static Arguments *pass_inputs[] = {&c_files, &i_files, &s_files, &o_files};
  73.  
  74. static char const *cpp_init_args[] = {CPP, "-S", "-D__TOS__", "-D__C68__", NULL},
  75.           *cc1_init_args[] = {CC1, NULL},
  76.           *as_init_args[] = {AS, NULL},
  77.           *lnk_init_args[] = {LNK, "-p", NULL},
  78.           *cpp_ansi_args[] = {"-ansi", "-T", NULL},
  79.           *fplib_args[] = {"-u", "__doprnt", "-u", "__scanf", NULL},
  80.           *cpp_asm_args[] = {"-P0", "-Wno-bad-chars",
  81.                      "-Wno-bad-concat-tokens", NULL};
  82. #define N_CPP_ASM_ARGS    3
  83.  
  84. char *argv0;
  85. int action = 1,
  86.     verbose = 0;
  87.  
  88. static const char *INCLUDE, *LIB, *TMPDIR, *outfnam = 0;
  89. static int last_stage = DO_LINK,
  90.        fp_lib = 0,
  91.        debug = 0,
  92.        keep = 0,
  93.        warn_level = DEFAULT_WARN_LVL,
  94.        long_int = 0,
  95.        profile = 0,
  96.        ansi = 1;
  97.  
  98. static void usage()
  99. {
  100.   fprintf(stderr, "usage: %s {args}\n", argv0);
  101.   exit(0);
  102. }
  103.  
  104. static void long_option(s)
  105.   const char *s;
  106. {
  107.   if (strcmp(s, "-mshort") == 0)
  108.     long_int = 0;
  109.   else if (strcmp(s, "-mlong") == 0)
  110.     long_int = 1;
  111.   else if (strcmp(s, "-ansi") == 0)
  112.     ansi = 1;
  113.   else if (strcmp(s, "-trad") == 0)
  114.     ansi = 0;
  115.   else {
  116.     error("unrecognized option '%s'", s);
  117.     usage();
  118.   }
  119. }
  120.  
  121. static void rename_stage(param)
  122.   const char *param;
  123. {
  124.   static char errmsg[] = "Invalid -N argument %s";
  125.  
  126.   if (param[1] != '=') {
  127.     error(errmsg, param);
  128.     return;
  129.   }
  130.   switch (*param) {
  131.     case 'P':
  132.       cpp_args._args[0] = param + 2;
  133.       return;
  134.     case 'C':
  135.       cc1_args._args[0] = param + 2;
  136.       return;
  137.     case 'A':
  138.       as_args._args[0] = param + 2;
  139.       return;
  140.     case 'L':
  141.       lnk_args._args[0] = param + 2;
  142.       return;
  143.     default:
  144.       error(errmsg, param);
  145.   }
  146. }
  147.  
  148. static char *lib_name_opts(lnam, which)
  149.   const char *lnam;
  150.   int which;
  151. {
  152.   static char buf[128];
  153.  
  154.   switch (which) {
  155.     case 1:
  156.       sprintf(buf, "lib%s%s%s.a", lnam, (profile ? "p" : ""),
  157.           (long_int ? "32" : ""));
  158.       return buf;
  159.     case 2:
  160.       sprintf(buf, "%s.%c%s", lnam, (profile ? 'p' : 'l'),
  161.           (long_int ? "32" : profile ? "lb" : "ib"));
  162.       return buf;
  163.    default:
  164.       bugchk("lib_name_opts(%d)?", which);
  165.       return 0;
  166.   }
  167. }
  168.  
  169. static void add_lib(lnam)
  170.   const char *lnam;
  171. {
  172.   char *s;
  173.   int i;
  174.  
  175.   for (i = 1; i <= N_LIB_FORMS; i++) {
  176.     s = lib_name_opts(lnam, i);
  177.     s = findfile(s, LIB, (char * const *)0);
  178.     if (s)
  179.       break;
  180.   }
  181.   if (s)
  182.     add_arg(&o_files, strdup(s));
  183.   else
  184.     error("no corresponding library found for parameter -l%s", lnam);
  185. }
  186.  
  187. static void add_lib_file(which)
  188.   int which;
  189. {
  190.   switch (which) {
  191.     case LF_STARTUP:
  192.       {
  193.     char *s = mallok(strlen(RT_STARTUP) + 1);
  194.  
  195.     sprintf(s, RT_STARTUP, (profile ? "p" : ""));
  196.     add_arg(&o_files, s);
  197.       }
  198.       break;
  199.     case LF_MATHLIB:
  200.       add_lib("m");
  201.       break;
  202.     case LF_STDCLIB:
  203.       add_lib("c");
  204.       break;
  205.     default:
  206.       bugchk("add_lib_file(%d)?", which);
  207.   }
  208. }
  209.  
  210. static void add_input_file(fnam, stage)
  211.   const char *fnam;
  212.   int stage;
  213. {
  214.   add_arg(pass_inputs[stage], fnam);
  215.   if (last_stage == DO_LINK && stage <= DO_ASSEMBLE)
  216.     add_arg(&o_files, derive_dest(fnam, DO_ASSEMBLE));
  217. }
  218.  
  219. static void remove_temp_files(state)
  220.   int state;
  221. {
  222.   char const **p;
  223.  
  224.   if (temp_files.nargs == 0 || args(&temp_files) == 0 || keep)
  225.     return;
  226.  
  227.   temp_files.nargs = 0;
  228.   for (p = args(&temp_files); *p; p++) {
  229.     if ((*p)[strlen(*p) - 1] == 'o' && state == RM_INTERMED) {
  230.       args(&temp_files)[temp_files.nargs++] = *p;
  231.     } else {
  232.       if (verbose || !action)
  233.     printf("rm -f %s\n", *p);
  234.       if (action)
  235.     unlink(*p);
  236.       free(*p);
  237.     }
  238.   }
  239.   args(&temp_files)[temp_files.nargs] = 0;
  240. }
  241.  
  242. static void panic_remove_temps()
  243. {
  244.   action = 1;
  245.   verbose = 0;
  246.   remove_temp_files(RM_FINAL);
  247. }
  248.  
  249. static const char *derive_dest(fnam, stage)
  250.   const char *fnam;
  251.   int stage;
  252. {
  253.   static char exts[] = {'i', 's', 'o'};
  254.   char *s = mallok(2 + strlen(fnam) + strlen(TMPDIR));
  255.   const char *t = strrchr(fnam, '.');
  256.  
  257.   if (!t)
  258.     bugchk("in derive_dest():  \"%s\" has no extension", fnam);
  259.  
  260.   if (stage == last_stage && outfnam)
  261.     return outfnam;
  262.  
  263.   sprintf(s, "%.*s.%c", (int)(t - fnam), fnam, exts[stage]);
  264.   if (stage < last_stage && access(s, F_OK) < 0) {
  265.     register const char **p;
  266.  
  267.     sprintf(s, "%s\\%.*s.%c", TMPDIR, (int)(t - fnam), fnam, exts[stage]);
  268.     /* Temporary .o files might already be on the list; check to avoid
  269.        duplicates. */
  270.     for (p = args(&temp_files); p && *p; p++) {
  271.       if (strcmp(*p, s) == 0)
  272.     break;
  273.     }
  274.     if (!p || !*p)
  275.       add_arg(&temp_files, s);
  276.   }
  277.   return s;
  278. }
  279.  
  280. static void process_file(fnam, first_stage)
  281.   const char *fnam;
  282.   int first_stage;
  283. {
  284.   int i, cpp_asm_flag = 0;
  285.   const char *inf = fnam;
  286.   const char *outf;
  287.  
  288.   if (first_stage == DO_PREPROCESS) {
  289.     const char *t = strrchr(fnam, '.');
  290.  
  291.     if (!t)
  292.       bugchk("in process_file():  \"%s\" has no extension", fnam);
  293.     cpp_asm_flag = ((strcmp(t + 1, "cpp") == 0) ||
  294.             (strcmp(t + 1, "spp") == 0));
  295.     if (cpp_asm_flag) {
  296.       add_args(&cpp_args, cpp_asm_args);
  297.       if (last_stage < DO_COMPILE)
  298.     error("-P/-E flags incompatible with input file %s", fnam);
  299.     }
  300.   }
  301.  
  302.   for (i = first_stage; i <= UP_TO_LINK; i++) {
  303.     outf = derive_dest(fnam, i + (cpp_asm_flag && i == DO_PREPROCESS));
  304.     add_arg(passes[i], inf);
  305.     add_arg(passes[i], outf);
  306.     run(passes[i], args(&new_env));
  307.     remove_args(passes[i], 2);
  308.     inf = outf;
  309.     if (cpp_asm_flag && i == DO_PREPROCESS)
  310.       i++;
  311.   }
  312.   if (cpp_asm_flag)
  313.     remove_args(&cpp_args, N_CPP_ASM_ARGS);
  314. #if 0
  315.   if (last_stage == DO_LINK)
  316.     add_arg(&o_files, outf);
  317. #endif
  318.   remove_temp_files(RM_INTERMED);
  319. }
  320.  
  321. int main(argc, argv, envp)
  322.   int argc;
  323.   char **argv;
  324.   char **envp;
  325. {
  326.   int i;
  327.   int got_file_args = 0;
  328.   char *s;
  329.   const char **p;
  330.  
  331.   if (argc == 1)
  332.     usage();
  333.   argv0 = argv[0];
  334.   atexit(panic_remove_temps);
  335.  
  336.   add_args(&cpp_args, cpp_init_args);
  337.   add_args(&cc1_args, cc1_init_args);
  338.   add_args(&as_args, as_init_args);
  339.   add_args(&lnk_args, lnk_init_args);
  340.   add_lib_file(LF_STARTUP);
  341.  
  342.   if (!(INCLUDE = getenv(INC_ENV_VAR)))
  343.     INCLUDE = DEFAULT_INC;
  344.   if (!(LIB = getenv(LIB_ENV_VAR)))
  345.     LIB = DEFAULT_LIB;
  346.   s = mallok(9 + strlen(INCLUDE));
  347.   sprintf(s, "INCLUDE=%s", INCLUDE);
  348.   add_arg(&new_env, s);
  349.   s = mallok(5 + strlen(LIB));
  350.   sprintf(s, "LIB=%s", LIB);
  351.   add_arg(&new_env, s);
  352.   add_args(&new_env, (char const * const *)envp);
  353.  
  354.   TMPDIR = getenv("TEMP");
  355.   if (!TMPDIR)
  356.     TMPDIR = getenv("TMP");
  357.   if (!TMPDIR)
  358.     TMPDIR = getenv("TMPDIR");
  359.   if (!TMPDIR)
  360.     TMPDIR = ".";
  361. #ifdef __MINT__
  362.   /* if temp dir is in Unix format, change it to DOS format so that jas
  363.      doesn't get confused */
  364.   if (strchr(TMPDIR, '/') != 0) {
  365.     static char dos_tmpdir[128];
  366.  
  367.     _unx2dos(TMPDIR, dos_tmpdir);
  368.     TMPDIR = dos_tmpdir;
  369.   }
  370. #endif
  371.  
  372.   for (i = 1; i < argc; i++) {
  373.     if (argv[i][0] == '-') {
  374.       switch(argv[i][1]) {
  375.     case 'E':
  376.       outfnam = "-";
  377.       /* and fall through */
  378.     case 'P':
  379.       last_stage = DO_PREPROCESS;
  380.       break;
  381.     case 'S':
  382.       last_stage = DO_COMPILE;
  383.       break;
  384.     case 'c':
  385.       last_stage = DO_ASSEMBLE;
  386.       break;
  387.     case 'D':
  388.     case 'U':
  389.     case 'I':
  390.       add_arg(&cpp_args, argv[i]);
  391.       break;
  392.     case 'O':
  393.       add_arg(&cc1_args, argv[i]);
  394.       break;
  395.     case 'L':
  396.       add_arg(&lnk_args, argv[i]);
  397.       break;
  398.     case 'N':
  399.       rename_stage(argv[i] + 2);
  400.       break;
  401.     case 'o':
  402.       outfnam = argv[++i];
  403.       break;
  404.     case 'l':
  405.       add_lib(argv[i] + 2);
  406.       break;
  407.     case 'f':
  408.       fp_lib = 1;
  409.       break;
  410.     case 'g':
  411.       debug = 1;
  412.       break;
  413.     case 'n':
  414.       action = 0;
  415.       break;
  416.     case 'v':
  417.       verbose++;
  418.       break;
  419.     case 't':
  420.       keep = 1;
  421.       break;
  422.     case 'p':
  423.       profile = 1;
  424.       break;
  425.     case 'W':
  426.       {
  427.         char c = argv[i][2];
  428.  
  429.         if (!c || c < '0' || c > '6' || argv[i][3]) {
  430.           error("invalid warning level '%s'", argv[i] + 2);
  431.           warn_level = DEFAULT_WARN_LVL;
  432.         } else
  433.           warn_level = c - '0';
  434.       }
  435.       break;
  436.     case 'V':
  437.       fprintf(stderr, "cc68x v%d.%d.%d\n",
  438.           MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL);
  439.       break;
  440.     default:
  441.       long_option(argv[i]);
  442.       }
  443.     } else if (argv[i][0] == '+') {
  444.       switch (argv[i][1]) {
  445.     case 'P':
  446.       add_arg(&cpp_args, argv[i] + 2);
  447.       break;
  448.     case 'C':
  449.       add_arg(&cc1_args, argv[i] + 2);
  450.       break;
  451.     case 'A':
  452.       add_arg(&as_args, argv[i] + 2);
  453.       break;
  454.     case 'L':
  455.       add_arg(&lnk_args, argv[i] + 2);
  456.       break;
  457.     default:
  458.       error("unrecognized option '%s'", argv[i]);
  459.       usage();
  460.       }
  461.     } else {
  462.       got_file_args = 1;
  463.       s = strrchr(argv[i], '.');
  464.       if (!s)
  465.     add_input_file(argv[i], DO_LINK);
  466.       else if (s[1] == 'c' && s[2] == '\0')
  467.     add_input_file(argv[i], DO_PREPROCESS);
  468.       else if ((strcmp(s + 1, "cpp") == 0) ||
  469.            (strcmp(s + 1, "spp") == 0))
  470.     add_input_file(argv[i], DO_PREPROCESS);
  471.       else if (s[1] == 'i' && s[2] == '\0')
  472.     add_input_file(argv[i], DO_COMPILE);
  473.       else if (s[1] == 's' && s[2] == '\0')
  474.     add_input_file(argv[i], DO_ASSEMBLE);
  475.       else
  476.     add_input_file(argv[i], DO_LINK);
  477.     }
  478.   }
  479.  
  480.   if (got_file_args == 0)
  481.     fatal("no files specified");
  482.  
  483.   if (fp_lib)
  484.     add_args(&lnk_args, fplib_args);
  485.   if (debug) {
  486.     add_arg(&cc1_args, "-g");
  487.     add_arg(&as_args, "-L1");
  488.     add_arg(&lnk_args, "-t");
  489.   }
  490.   if (verbose > 1) {
  491.     add_arg(&cpp_args, "-V");
  492.     add_arg(&cc1_args, "-v");
  493.     add_arg(&as_args, "-v");
  494.     add_arg(&lnk_args, "-v");
  495.   }
  496.   if (long_int) {
  497.     add_arg(&cc1_args, "-noshort");
  498.   } else {
  499.     add_arg(&cpp_args, "-D__MSHORT__");
  500.   }
  501.   if (ansi)
  502.     add_args(&cpp_args, cpp_ansi_args);
  503.   else
  504.     add_arg(&cc1_args, "-trad");
  505.   if (warn_level != DEFAULT_WARN_LVL) {
  506.     static char warn_opt[] = "-warn=3";
  507.  
  508.     warn_opt[6] = (char)(warn_level + '0');
  509.     add_arg(&cc1_args, warn_opt);
  510.   }
  511.  
  512.   for (i = DO_PREPROCESS; i <= UP_TO_LINK; i++) {
  513.     for (p = args(pass_inputs[i]); p && *p; p++) {
  514.       process_file(*p, i);
  515.     }
  516.   }
  517.   if (last_stage == DO_LINK) {
  518.     if (fp_lib)
  519.       add_lib_file(LF_MATHLIB);
  520.     add_lib_file(LF_STDCLIB);
  521.     add_arg(&lnk_args, "-o");
  522.     add_arg(&lnk_args, (outfnam ? outfnam : DEFAULT_EXEC));
  523.     add_args(&lnk_args, args(&o_files));
  524.     run(&lnk_args, args(&new_env));
  525.   }
  526.  
  527.   remove_temp_files(RM_FINAL);
  528.   return 0;
  529. }
  530.